
import { toRaw } from 'vue'
// import type { InjectionKey } from 'vue'

import type {
  IState,
  IStateKey
  // IArrayOrFunction
} from '../types/type'


/**
 * 继承 Array 实现 IState 接口，实现辅助功能
 */
export default class BaseArray<T> extends Array implements IState {
  #id: IStateKey
  #_value : Array<T> | (() => Array<T>)

  /**
   * 数组的辅助工具
   * @param arrayOrFunction 初始值，数组或者函数
   * @param id 标识
   */
  constructor (arrayOrFunction: Array<T> | (() => Array<T>), id: IStateKey = Symbol('_array')) {
    // 调用父类的 constructor()
    super()
    this.#id = id
    this.#_value = arrayOrFunction
    let arr = arrayOrFunction
    if (typeof arrayOrFunction === 'function') {
      arr = arrayOrFunction()
    }
    // 设置初始值
    if (Array.isArray(arr)) {
      if (arr.length > 0) this.push(...arr)
    } else {
      if (arr) this.push(arr)
    }
  }

  /**
   * 获取初始值
   */
  get $value() {
    const val = toRaw(this).#_value
    if (typeof val === 'function')
      return val()
    else
      return []
  }

  /**
   * 只支持函数形式的初始值
   */
  $reset() {
    // 
    if (this.$value.length > 0) {
      this.$state = this.$value
    } else {
      console.log('$reset() 只支持函数形式的初始值')
    }
  }
  /**
   * 没有实现功能，仅兼容 对象基类的方法
   */
  $patch() {
    console.log('没有实现数组的 $patch()')
  }

  /**
   * 整体替换，会清空原数组，
   */
  set $state(value: Array<T> | T) {
    // 删除原有数据
    this.length = 0
    if (Array.isArray(value)) {
      this.push(...value)
    } else {
      this.push(value)
    }
  }

  /**
   * 取原型，不包含内部方法，不维持响应性
   */
  $toRaw<T>(): Array<T> {
    const arr: Array<T> = []
    const tmp = toRaw(this)
    tmp.forEach(item => {
      const _item = toRaw(item)
      arr.push( (_item.$toRaw) ? _item.$toRaw() : _item )
    })
    return arr
  }
  
  /**
   * 获取ID
   */
  get $id() {
    return toRaw(this).#id
  }

  /**
   * 获取是否记录日志
   */
  get $isLog() {
    return false
  }
  
  /**
   * 获取是不是状态
   */
  get $isState() {
    return false
  }
  /**
   * 获取是不是数组类型的状态
   */
  get $isArray() {
    return true
  }
  /**
   * 获取是否对象类型的状态
   */
  get $isObject() {
    return false
  }
  /**
   * 数组不记录日志
   */
  get $logs() {
    return []
  }
  
  /**
   * 清空日志
   */
  $clearLog() {
    // 
  }

  // 添加元素   ==========================================
  /**
   * 在开头添加，封装 unshift
   * @returns 返回新数组的长度
   */
  $pushA(...arg: Array<any>) {
    return this.unshift(...arg)
  }

  /**
   * 在指定位置i开始添加新元素，封装 splice
   * @param i 从 0 开始的位置
   * @param val 要添加的新元素
   * @returns 返回新数组的长度
   */
  $pushAt(i: number, ...arg: Array<any>) {
    // console.log(arguments)
    this.splice(i, 0, ...arg)
  }

  // 删除元素 ==========================================
  /**
   * 删除第一个元素
   * @returns 返回被删除的元素
   */
  $deleteA() {
    this.shift()
  }

  /**
   * 删除从指定位置 i 开始的 n 个元素，返回被删掉的函数
   * @param i 从 0 开始的位置
   * @param n 删除多少个元素
   * @returns 返回被删除的元素
   */
  $deleteAt<T>(i: number, n: number) {
    const re = this.splice(i, n) as BaseArray<T>
    return re.$toRaw()
  }

  /**
   * 删除最后一个元素，封装 pop
   * @returns 返回被删除的元素
   */
  $deleteZ() {
    this.pop()
  }

  // 修改元素位置==========================================
  /**
   * 交换两个数组元素的位置
   * @param i1 数组下标 
   * @param i2 数组下标 
   */
  $swap(i1: number, i2: number) {
    const tmp = this[i1]
    this[i1] = this[i2]
    this[i2] = tmp
  }
  // 查找类==========================================
  // 其他类==========================================


}
